package com.htthorizon.datascope;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.htthorizon.common.core.utils.StringUtils;
import com.htthorizon.common.security.utils.SecurityUtils;
import com.htthorizon.model.response.RemoteDataInfoDto;
import com.htthorizon.model.service.IModelCrossAuditService;
import com.htthorizon.system.api.domain.SysDept;
import com.htthorizon.system.api.domain.SysUser;
import com.htthorizon.system.api.model.LoginUser;
import com.htthorizon.util.ServiceMarketHTTPUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author Brilliant ,
 */
@Component
@Slf4j
public class DataScopeUtil {

    @Autowired
    private IModelCrossAuditService modelCrossAuditService;

    @Autowired
    private ServiceMarketHTTPUtil serviceMarketHTTPUtil;

    public List<RemoteDataInfoDto> getDataByUserDept(String metaAppkey, String metaAppsecre, String requestUrl, Map<String, Object> paramsMap) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        // 计算总页大小
        List<String> deptListByUser = this.getDeptListByUser();
        int total=0;
        for (String str : deptListByUser){
            Integer i = this.filterDataByDeptCount(metaAppkey, metaAppsecre, requestUrl, str, paramsMap);
            total+=i;
        }
        List<RemoteDataInfoDto> list = this.buildPage(total);
        for(RemoteDataInfoDto remoteDataInfoDto: list){
            Integer pageNum = remoteDataInfoDto.getPageNum();
            Integer pageSize = remoteDataInfoDto.getPageSize();
            paramsMap.put("pageNum",pageNum.toString());
            paramsMap.put("pageSize",pageSize.toString());
            List<Object> tempList=new ArrayList<>();
            for (String str : deptListByUser){
                List<Object> objects = (List<Object>)this.filterDataByUserDept(metaAppkey, metaAppsecre, requestUrl, str, paramsMap);
                tempList.addAll(objects);
            }
            remoteDataInfoDto.setRows(tempList);
        }
        return list;
    }


    public Integer filterDataByDeptCount(String appKey,String appSecurty,String path,String dept,Map<String,Object> paramsMap) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        paramsMap.put("std_city_org_nm",dept);
        String parameter = serviceMarketHTTPUtil.getParamString(paramsMap);
        String result = serviceMarketHTTPUtil.getMethod("",appKey, appSecurty, path, parameter);
        if(StringUtils.isNotEmpty(result)) {
            Optional<RemoteDataInfoDto> dataOpt = null;
            try {
                JSONObject jsonObject = JSON.parseObject(result);
                dataOpt = Optional.ofNullable(JSONObject.parseObject(jsonObject.getString("data"), RemoteDataInfoDto.class));
            } catch (JSONException e) {
            }
            if (dataOpt.isPresent()) {
                RemoteDataInfoDto dataInfoDto = dataOpt.get();
                return  Integer.valueOf(dataInfoDto.getTotalNum());
            }
        }
        return null;
    }

    public List<?> filterDataByUserDept(String appKey,String appSecurty,String path,String dept,Map<String,Object> paramsMap) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        paramsMap.put("std_city_org_nm",dept);
        String parameter = serviceMarketHTTPUtil.getParamString(paramsMap);
        String result = serviceMarketHTTPUtil.getMethod("",appKey, appSecurty, path, parameter);
        if(StringUtils.isNotEmpty(result)) {
            Optional<RemoteDataInfoDto> dataOpt = null;
            try {
                JSONObject jsonObject = JSON.parseObject(result);
                dataOpt = Optional.ofNullable(JSONObject.parseObject(jsonObject.getString("data"), RemoteDataInfoDto.class));
            } catch (JSONException e) {
            }
            if (dataOpt.isPresent()) {
                RemoteDataInfoDto dataInfoDto = dataOpt.get();
               return dataInfoDto.getRows();
            }
        }
        return null;
    }

    public String filterDataByDept(String result){
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        SysDept dept = Optional.ofNullable(sysUser.getDept())
                                .orElse(new SysDept());
        if (sysUser.isAdmin()){
            return result;
        }

        List<String> modelCrossAuditStringList = modelCrossAuditService.getModelCrossAuditStringList();
        modelCrossAuditStringList.add(dept.getDeptName());
//
//        SysDept dept = new SysDept();
//        dept.setDeptName("长沙");

        if(StringUtils.isNotEmpty(result)) {
            Optional<RemoteDataInfoDto> dataOpt = null;
            try {
                JSONObject jsonObject = JSON.parseObject(result);
                dataOpt = Optional.ofNullable(JSONObject.parseObject(jsonObject.getString("data"), RemoteDataInfoDto.class));
            }catch (JSONException e){

            }
            if (dataOpt.isPresent()) {
                RemoteDataInfoDto dataInfoDto = dataOpt.get();

                List<?> dataList = dataInfoDto.getRows();
                List<Object> newList=new ArrayList<>();
                //设置表头,获取api返回数据中的一条数据，设置中文字段表头
                if(StringUtils.isNotEmpty(dataList)) {

                    for (int i=0;i<dataList.size();i++) {
                        Map<String, Object> dataMap = (Map<String, Object>) dataList.get(i);
                        for(String fieldName:dataMap.keySet()){
                            if ("std_city_org_nm".equals(fieldName)){
                                String str = (String)dataMap.get(fieldName);
                                if (StringUtils.isNotEmpty(str)&&this.matching(str,modelCrossAuditStringList)){
                                    newList.add(dataMap);
                                }
                            }
                        }
                    }
                }
                dataInfoDto.setRows(newList);
                dataInfoDto.setTotalNum(newList.size());
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("data",dataInfoDto);
                return JSON.toJSONString(jsonObject);
            }
        }

        return null;
    }

    public boolean matching(String str1,List<String> str2){
        if(StringUtils.isEmpty(str1)) return false;
        int i=0;
        for (String str:str2){
            try {
                if (str1.contains(str)) i++;
            }catch (NullPointerException e){

                log.warn("数据权限匹配地市中存在空值");
            }
        }
        return i > 0;
    }

    public String getDataByUser(String metaAppkey, String metaAppsecre, String requestUrl, Map<String, Object> paramsMap) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        RemoteDataInfoDto remoteDataInfoDto = new RemoteDataInfoDto();
        Integer total=0;
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        SysDept dept = Optional.ofNullable(sysUser.getDept())
                .orElse(new SysDept());
        List<String> modelCrossAuditStringList = modelCrossAuditService.getModelCrossAuditStringList();
        modelCrossAuditStringList.add(dept.getDeptName());
        for (String deptName:modelCrossAuditStringList){
            Integer i = this.filterDataByDeptCount(metaAppkey, metaAppsecre, requestUrl, deptName,paramsMap);
            total=i+total;
        }
        remoteDataInfoDto.setTotalNum(total);
        remoteDataInfoDto.setPageNum(Integer.valueOf((String) paramsMap.get("pageNum")) );
        remoteDataInfoDto.setPageSize(Integer.valueOf((String)paramsMap.get("pageSize")));
        for (String deptName:modelCrossAuditStringList) {
            try {
              return  this.getData(metaAppkey, metaAppsecre, requestUrl, deptName, paramsMap);
            } catch (Exception e) {
                continue;
            }
        }
        return null;
    }

    private String getData(String metaAppkey, String metaAppsecre, String requestUrl, String deptName, Map<String, Object> paramsMap) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        paramsMap.put("std_city_org_nm",deptName);
        String parameter = serviceMarketHTTPUtil.getParamString(paramsMap);
        return serviceMarketHTTPUtil.getMethod("",metaAppkey, metaAppsecre, requestUrl, parameter);
    }

    private List<String> getDeptListByUser(){
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        SysDept dept = Optional.ofNullable(sysUser.getDept())
                .orElse(new SysDept());
        List<String> modelCrossAuditStringList = modelCrossAuditService.getModelCrossAuditStringList();
        modelCrossAuditStringList.add(dept.getDeptName());
        return modelCrossAuditStringList;
    }

    private final static Integer span=2000;

    private List<RemoteDataInfoDto> buildPage(Integer total){
        List<RemoteDataInfoDto> list=new ArrayList<>();
        if (span >= total) {
            RemoteDataInfoDto remoteDataInfoDto=new RemoteDataInfoDto();
            remoteDataInfoDto.setPageNum(1);
            remoteDataInfoDto.setPageSize(span);
            list.add(remoteDataInfoDto);
            return list;
        }
        int size = total / span;
        if (total % span != 0){
            for (int i = 1; i <= size + 1; i++) {
               RemoteDataInfoDto remoteDataInfoDto=new RemoteDataInfoDto();
                remoteDataInfoDto.setPageNum(size);
                remoteDataInfoDto.setPageSize(span);
                list.add(remoteDataInfoDto);
            }
        } else {
            for (int i = 1; i <= size; i++) {
                RemoteDataInfoDto remoteDataInfoDto=new RemoteDataInfoDto();
                remoteDataInfoDto.setPageNum(size);
                remoteDataInfoDto.setPageSize(span);
                list.add(remoteDataInfoDto);
            }
        }
        return list;
    }

}
